import string

def targets():
  return [c]

class AvailabilityProc:
  def __init__(self, name, type):
    self.name = name
    self.type = type

class AvailabilityArgument:
  def __init__(self, id=None, name=None, datatype=None, type=None, intent=None, length=None):
    self.id = id
    self.name = name
    self.datatype = datatype
    self.type = type
    self.intent = intent
    
  def __str__(self):
    res = ""
    res += "      <id%d> <!-- %s -->\n" % (self.id, self.name)
    res += "        <E id = \"%s\"/>\n" % (self.id)
    res += "        <E datatype = \"%s\"/>\n" % (self.datatype[:-1])
    res += "        <E type = \"%s\"/>\n" % (self.type)
    res += "        <E intent = \"%s\"/>\n" % (self.intent)
    res += "      </id%d>\n" % (self.id)

    return res

  def format(self):
    if self.type == "stream":
      fmt = "i"
    elif self.type == "int":
      fmt = "d"
    elif self.type == "double":
      fmt = "f"
    elif self.type == "pointer":
      fmt = "p"
    else:
      raise "Unknown format type"

    if self.intent == "in":
      return fmt
    elif self.intent == "out":
      return fmt.upper()

class Availability:
  def __init__(self, rpc, name, skeleton):
    self.rpc = rpc
    self.name = name
    self.skeleton = skeleton
    self.processors = []
    self.arguments = []

  def __str__(self):
    res = ""
    res += "  <%s>\n" % (self.name)
    res += "    <E id = \"%d\"/>\n" % (self.rpc)
    res += "    <E skeleton = \"%s\"/>\n" % (string.split(self.name, "-")[0])
    res += "    <E kernel = \"%s\"/>\n" % (string.split(self.name, "-")[1])
    res += "    <E line = \"%s\"/>\n" % (string.split(self.name, "-")[2])
    res += "    <arguments>\n"
    for a in self.arguments:
      res += str(a)
    res += "    </arguments>\n"
    res += "    <targets>\n"

    for p in self.processors:
      res += "      <%s>\n" % (p.name)
      res += "      </%s>\n" % (p.name)

    res += "    </targets>\n"
    res += "  </%s>\n" % (self.name)

    return res

class Target:
  pass

class c(Target):
  def __init__(self, input, merge=False):
    self.input = input
    if merge:
      fname = "ilpMergedOperationEnqueue"
    else:
      fname = "ilpCustomOperationEnqueue"
    
    self.casetext = """
void %s(ilp_op_t *op)
{
  switch (op->operation)
  {
""" % (fname)
    self.kerneltext = ""

  def __repr__(self):
    return "c"
    
  def __str__(self):
    return self.__repr__()
    
  def ext(self):
    return ".c"
    
  def type(self):
    return 0;
    
  def addkernel(self, rpc, skeleton, kernel, code):
    self.casetext += """
    case %s:
      lprintf(STREAM(ilpl.notice), "%s(%s)");
      %s_%s_%s(op);
      break;
""" % (rpc, skeleton, kernel, skeleton, kernel, rpc)
    self.kerneltext += """
void %s_%s_%s(ilp_op_t *op)
{
  ilp_arg_t *args = op->argument;
%s
}
""" % (skeleton, kernel, rpc, code)    

  def write(self, extra=""):
    self.casetext += """
  }
}
"""
  
    self.text = """
#include <assert.h>
#include <math.h>
#include <log.h>
#include <scos.h>
#include "sc.h"
#include "scc.h"
#include "scu.h"
#include "scilp.h"

#ifdef PSOS
  #include <ops/custom_defs.h>
#endif

%s

extern log_default_streams_t ilpl;
extern scu_buf_t *ilp_buf;

%s

%s
""" % (extra, self.kerneltext, self.casetext)

    f = open(self.input + self.ext(), "w")
    print >>f, self.text
    f.close()
    
class xtc(Target):
  def __init__(self, input, merge=False):
    self.input = input
    self.text = """
#include "stdio.xtc"

#define MAXWORD 31

reg row, rows;

preg &task_in_io   = PREG0;
preg &task_in_type = PREG1;
preg &task_in_nr   = PREG2;
preg &task_out_fin = PREG3;

reg task0_type;
reg task0_io;
reg task1_type;
reg task1_io;
reg task2_type;
reg task2_io;
reg task3_type;
reg task3_io;
reg task4_type;
reg task4_io;
reg task5_type;
reg task5_io;
reg task6_type;
reg task6_io;

lmem &larg0 = LMEM0;
lmem &larg1 = LMEM1;
lmem &larg2 = LMEM2;
lmem &larg3 = LMEM3;
lmem &larg4 = LMEM4;
lmem &larg5 = LMEM5;

static RunTask(reg task_type, reg task_io)
{
  {
    reg idx = 0;
    reg temptaskio = task_io & 7;
    SETLMEMI idx, temptaskio;

    idx = 1;
    task_io >>= 3;
    temptaskio = task_io & 7;
    SETLMEMI idx, temptaskio;

    idx = 2;
    task_io >>= 3;
    temptaskio = task_io & 7;
    SETLMEMI idx, temptaskio;
  }

  /* Static tasks */
  if (task_type == 5)      /* Capture */
  {
    larg0 = INPUT+511;
  }
  else if (task_type == 6) /* Transport */
  {
    WriteLine(larg0, larg0, larg0);
  }
"""

  def __repr__(self):
    return "xtc"
    
  def __str__(self):
    return self.__repr__()
    
  def ext(self):
    return ".xtc"
    
  def type(self):
    return 1;
    
  def addkernel(self, rpc, skeleton, kernel, code):
    self.text += """
    else if (task_type == %s) /* %s(%s) */
    {
""" % (rpc, skeleton, kernel)
    self.text += code
    self.text += """
    }
"""

  def write(self, extra=""):
    self.text += """
}

static GetComms()
{
  if (task_in_nr != MAXWORD)
  {
    reg task_nr = task_in_nr;
    
    if (task_nr < 1)
    {
      task0_type = task_in_type;
      task0_io = task_in_io;
    } else if (task_nr < 2)
    {
      task1_type = task_in_type;
      task1_io = task_in_io;
    } else if (task_nr < 3)
    {
      task2_type = task_in_type;
      task2_io = task_in_io;
    } else if (task_nr < 4)
    {
      task3_type = task_in_type;
      task3_io = task_in_io;
    } else if (task_nr < 5)
    {
      task4_type = task_in_type;
      task4_io = task_in_io;
    } else if (task_nr < 6)
    {
      task5_type = task_in_type;
      task5_io = task_in_io;
    } else if (task_nr < 7)
    {
      task6_type = task_in_type;
      task6_io = task_in_io;
    }
    
    task_in_nr = MAXWORD;
  }
}

StartIO();

task_in_nr = MAXWORD;
task0_type = MAXWORD;
task1_type = MAXWORD;
task2_type = MAXWORD;
task3_type = MAXWORD;
task4_type = MAXWORD;
task5_type = MAXWORD;
task6_type = MAXWORD;

while(1)
{
  Vsync();

  GetMaxRow(rows);

  for (row=0; row < rows; rows++)
  { 
    Hsync();
    StartSerialProcessor();

    /* Get new comms. Uses global variables. */
    GetComms();

    /* Run tasks */
    if (task0_type != MAXWORD) RunTask(task0_type, task0_io);
    if (task1_type != MAXWORD) RunTask(task1_type, task1_io);
    if (task2_type != MAXWORD) RunTask(task2_type, task2_io);
    if (task3_type != MAXWORD) RunTask(task3_type, task3_io);
    if (task4_type != MAXWORD) RunTask(task4_type, task4_io);
    if (task5_type != MAXWORD) RunTask(task5_type, task5_io);
    if (task6_type != MAXWORD) RunTask(task6_type, task6_io);
  }
  
  task_out_fin = MAXWORD;

  GetBlankingLines(rows);
  StartFrameBlank();

  for (row=0; row < rows; row++)
  {
    Hsync();
    GetComms();
  }
} /* The Never Ending Story (Michael Eden) */
"""  

    f = open(self.input + self.ext(), "w")
    print >>f, self.text
    f.close()

class fpga(Target):
  def __init__(self, input, merge=False):
    self.input = input
    self.text = """
void fpgaCustomOperationEnqueue(int operation, sc_op_t *arg)
{
  switch (operation)
  {
"""    

  def __repr__(self):
    return "fpga"
    
  def __str__(self):
    return self.__repr__()
    
  def ext(self):
    return "_fpga.c"
    
  def type(self):
    return 0;
    
  def addkernel(self, rpc, skeleton, kernel, code):
    self.text += """
    case %s:
""" % (rpc)
    self.text += code
    self.text += """
      break;
"""

  def write(self, extra=""):
    self.text += """
  }
}
"""
    f = open(self.input + self.ext(), "w")
    print >>f, self.text
    f.close()
